[Chapter Eight][Previous]
[Next] [Art of
Assembly][Randall Hyde]
Art of Assembly: Chapter Eight
- 8.15 - Repeat Operations
- 8.16 - The FOR and FORC Macro Operations
- 8.17 - The WHILE Macro Operation
- 8.18 - Macro Parameters
8.15 Repeat Operations
Another macro format (at least by Microsoft's definition) is the repeat
macro. A repeat macro is nothing more than a loop that repeats the statements
within the loop some specified number of times. There are three types of
repeat macros provided by MASM: repeat/rept, for/irp,
and
forc/irpc.
The repeat/rept
macro uses the following
syntax:
repeat expression
<statements>
endm
Expression
must be a numeric expression that evaluates to an
unsigned constant. The repeat
directive duplicates all the
statements between repeat
and endm
that many times.
The following code generates a table of 26 bytes containing the 26 uppercase
characters:
ASCIICode = 'A'
repeat 26
byte ASCIICode
ASCIICode = ASCIICode+1
endm
The symbol ASCIICode
is assigned the ASCII code for "A".
The loop repeats 26 times, each time emitting a byte with the value of ASCIICode
.
Also, the loop increments the ASCIICode
symbol on each repetition
so that it contains the ASCII code of the next character in the ASCII table.
This effectively generates the following statements:
byte 'A'
byte 'B'
.
.
.
byte 'Y'
byte 'Z'
ASCIICode = 27
Note that the repeat
loop executes at assembly time, not at
run time. Repeat
is not a mechanism for creating loops within
your program; use it for replicating sections of code within your program.
If you want to create a loop that executes some number of times within your
program, use the loop
instruction. Although the following two
code sequences produce the same result, they are not the same:
; Code sequence using a run-time loop:
mov cx, 10
AddLp: add ax, [bx]
add bx, 2
loop AddLp
; Code sequence using an assembly-time loop:
repeat 10
add ax, [bx]
add bx, 2
endm
The first code sequence above emits four machine instructions to the object
code file. At assembly time, the 80x86 CPU executes the statements between
AddLp
and the loop
instruction ten times under
the control of the loop
instruction. The second code sequence
above emits 20 instructions to the object code file. At run time, the 80x86
CPU simply executes these 20 instructions sequentially, with no control
transfer. The second form will be faster, since the 80x86 does not have
to execute the loop instruction every third instruction. On the other hand,
the second version is also much larger because it replicates the body of
the loop ten times in the object code file.
Unlike standard macros, you do not define and invoke repeat
macros
separately. MASM emits the code between the repeat
and endm
directives upon encountering the repeat
directive. There isn't
a separate invocation phase. If you want to create a repeat
macro
that can be invoked throughout your program, consider the following:
REPTMacro macro Count
repeat Count
<statements>
endm
endm
By placing the repeat
macro inside a standard macro, you can
invoke the repeat
macro anywhere in your program by invoking
the REPTMacro
macro. Note that you need two endm
directives,
one to terminate the repeat
macro, one to terminate the standard
macro.
Rept
is a synonym for repeat
. Repeat
is
the newer form, MASM supports Rept
for compatibility with older
source files. You should always use the repeat
form.
8.16 The FOR and FORC Macro Operations
Another form of the repeat macro is the for
macro. This
macro takes the following form:
for parameter,<item1 {,item2 {,item3 {,...}}}>
<statements>
endm
The angle brackets are required around the items in the operand field of
the for
directive. The braces surround optional items, the
braces should not appear in the operand field.
The for
directive replicates the instructions between for
and endm
once for each item appearing in the operand field.
Furthermore, for each iteration, the first symbol in the operand field is
assigned the value of the successive items from the second parameter. Consider
the following loop:
for value,<0,1,2,3,4,5>
byte value
endm
This loop emits six bytes containing the values zero, one, two, ..., five.
It is absolutely identical to the sequence of instructions:
byte 0
byte 1
byte 2
byte 3
byte 4
byte 5
Remember, the for
loop, like the repeat
loop,
executes at assembly time, not at run time.
For
's second operand need not be a literal text constant; you
can supply a macro parameter, macro function result, or a text equate for
this value. Keep in mind, though, that this parameter must expand to a text
value with the text delimiters around it.
Irp
is an older, obsolete, synonym for for
. MASM
allows irp
to provide compatibility with older source code.
However, you should always use the for
directive.
The third form of the loop macro is the forc
macro. It differs
from the for
macro in that it repeats a loop the number of
times specified by the length of a character string rather than by the number
of operands present. The syntax for the forc
directive is
forc parameter,<string>
<statements>
endm
The statements in the loop repeat once for each character in the string
operand. The angle brackets must appear around the string. Consider the
following loop:
forc value,<012345>
byte value
endm
This loop produces the same code as the example for the for
directive
above.
Irpc
is an old synonym for forc
provided for compatibility
reasons. You should always use forc
in your new code.
8.17 The WHILE Macro Operation
The while
macro lets you repeat a sequence of code in your
assembly language file an indefinite number of times. An assembly time expression,
that while evaluates before emitting the code for each loop, determines
whether it repeats. The syntax for this macro is
while expression
<Statements>
endm
This macro evaluates the assembly-time expression; if this expression's
value is zero, the while
macro ignores the statements up to
the corresponding endm
directive. If the expression evaluates
to a non-zero value (true), then MASM assembles the statements up to the
endm
directive and reevaluates the expression to see if it
should assemble the body of the while
loop again.
Normally, the while
directive repeats the statements between
the while
and endm
as long as the expression evaluates
true. However, you can also use the exitm
directive to prematurely
terminate the expansion of the loop body. Keep in mind that you need to
provide some condition that terminates the loop, otherwise MASM will go
into an infinite loop and continually emit code to the object code file
until the disk fills up (or it will simply go into an infinite loop if the
loop does not emit any code).
8.18 Macro Parameters
Standard MASM macros are very flexible. If the number of actual parameters
(those supplied in the operand field of the macro invocation) does not match
the number of formal parameters (those appearing in the operand field of
the macro definition), MASM won't necessarily complain. If there are more
actual parameters than formal parameters, MASM ignores the extra parameters
and generates a warning. If there are more formal parameters than actual
parameters, MASM substitutes the empty string ("<>") for
the extra formal parameters. By using the ifb
and ifnb
conditional assembly directives, you can test this last condition. While
this parameter substitution technique is flexible, it also leaves open the
possibility of error. If you want to require that the programmer supply
exactly three parameters and they actually supply less, MASM will not generate
an error. If you forget to test for the presence of each parameter using
ifb
, you could generate bad code. To overcome this limitation,
MASM provides the ability to specify that certain macro parameters are required.
You can also assign a default value to a parameter if the programming doesn't
supply one. Finally, MASM also provides facilities to allow a variable number
of macro arguments.
If you want to require a programmer to supply a particular macro parameters,
simply put ":req
" after the macro parameter in the
macro definition. At assembly time, MASM will generate an error if that
particular macro is missing.
Needs2Parms macro parm1:req, parm2:req
.
.
.
endm
.
.
.
Needs2Parms ax ;Generates an error.
Needs2Parms ;Generates an error.
Needs2Parms ax, bx ;Works fine.
Another possibility is to have the macro supply a default value for a macro
if it is missing from the actual parameter list. To do this, simply use
the ":=<text>" operator immediately after the parameter
name in the formal parameter list. For example, the int 10h
BIOS function provides various video services. One of the most commonly
used video services is the ah=0eh
function that outputs the
character in al
to the video display. The following macro lets
the caller specify which function they want to use, and defaults to function
0eh
if they don't specify a parameter:
Video macro service := <0eh>
mov ah, service
int 10h
endm
The last feature MASM's macros support is the ability to process a variable
number of parameters. To do this you simply place the operator ":vararg
"
after the last formal parameter in the parameter list. MASM associates the
first n actual parameters with the corresponding formal parameters appearing
before the variable argument, it then creates a text equate of all remaining
parameters to the formal parameter suffixed with the ":vararg
"
operator. You can use the for
macro to extract each parameter
from this variable argument list. For example, the following macro lets
you declare an arbitrary number of two dimensional arrays, all the same
size. The first two parameters specify the number of rows and columns, the
remaining optional parameters specify the names of the arrays:
MkArrays macro NumRows:req, NumCols:req, Names:vararg
for AryName, Names
&AryName& word NumRows dup (NumCols dup (?))
endm
endm
.
.
.
MkArrays 8, 12, A, B, X, Y
- 8.15 - Repeat Operations
- 8.16 - The FOR and FORC Macro Operations
- 8.17 - The WHILE Macro Operation
- 8.18 - Macro Parameters
Art of Assembly: Chapter Eight - 26 SEP 1996
[Chapter Eight][Previous]
[Next] [Art of
Assembly][Randall Hyde]